﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.AudioVideoPlayback;
using Microsoft.Win32;

namespace SubtitlesCleaner
{
    class Program
    {
        static StringBuilder log = new StringBuilder();
        static String TITLE = "Subtitles Cleaner!";
        static String REGISTRY_KEY = "SubtitlesCleaner";
        static double defaultFps = 23.976;
        public static MessageBoxIcon status = MessageBoxIcon.None;

        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0)
                {
                    CheckAssociation();
                    log.AppendLine(Resources.ContextMenuAdded);
                    log.AppendLine(Resources.ContextMenuAddedInfo);
                    status = MessageBoxIcon.Information;
                }
                else
                {
                    convert(String.Join(" ", args));
                }
            }
            catch (Exception e)
            {
                log.AppendLine();
                log.AppendLine(Resources.FatalError);
                log.AppendLine();
                log.AppendLine(e.Message);
                log.AppendLine();
                log.AppendLine(e.StackTrace);
            }
            if (status != MessageBoxIcon.None)
            {
                MessageBox.Show(log.ToString(), TITLE, MessageBoxButtons.OK, status, MessageBoxDefaultButton.Button1);
            }
            Console.WriteLine(log.ToString());
        }

        private static void convert(string file)
        {
            if (File.Exists(file))
            {
                log.Append(Resources.SubtitlesFileConversion);
                log.Append(" : ");
                log.AppendLine(file);

                String videoFile = file.Replace(".txt", ".avi");
                if (!File.Exists(videoFile))
                    videoFile = file.Replace(".txt", ".mkv");
                if (!File.Exists(videoFile))
                    videoFile = file.Replace(".txt", ".mp4");

                if (File.Exists(videoFile))
                {
                    List<string> lines = readFile(file);
                    
                    log.Append(Resources.VideoFile);
                    log.Append(": ");
                    log.AppendLine(videoFile);

                    double rate = getFrameRate(videoFile);
                    String newFile = new SubtitleFile(file, rate, lines).exportToSubRip();
                    File.Delete(file);
                    file = file.Replace(".txt", ".srt");
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                    File.Move(newFile, file);
                }
                else
                {
                    log.AppendLine(Resources.VideoFileNotExistsError);
                    log.AppendLine();
                    log.AppendLine(videoFile);
                    status = MessageBoxIcon.Error;
                }
            }
            else
            {
                log.AppendLine(Resources.SubtitlesFileNotExistsError);
                log.AppendLine(file);
                status = MessageBoxIcon.Error;
            }
        }

        static public double getFrameRate(string file)
        {
            double frameRate;

            try
            {
                Video v = Microsoft.DirectX.AudioVideoPlayback.Video.FromFile(file);
                frameRate = 1 / v.AverageTimePerFrame;
                log.Append(Resources.FrameRate);
                log.Append(": ");
                log.AppendLine(frameRate.ToString());
            }
            catch (Exception)
            {
                frameRate = defaultFps;
                log.AppendLine();
                log.AppendLine(Resources.Warning1);
                log.Append(Resources.Warning2);
                log.Append(Resources.FrameRate);
                log.Append(": ");
                log.AppendLine(frameRate.ToString());
                log.AppendLine(Resources.Warning3);
                status = MessageBoxIcon.Warning;
            }
            return frameRate;
        }

        static public List<string> readFile(string subtitlePath)
        {
            List<string> lines = new List<string>();
            bool isFirstLine = true;
            StreamReader sr = new StreamReader(subtitlePath, Encoding.Default);
            for (; ; )
            {
                string s = sr.ReadLine();

                if (s == null)
                    break;

                bool isTrash = false;

                foreach (string trash in SubtitlesFilter.Filter)
                {
                    if (s.ToLower().IndexOf(trash) > -1)
                    {
                        isTrash = true;
                        break;
                    }
                }
                if (!isTrash)
                {
                    lines.Add(s);
                }
                if (isFirstLine)
                {
                    if (s.Contains("23"))
                        defaultFps = 23.97;
                    else if (s.Contains("25"))
                        defaultFps = 25f;
                    else if (s.Contains("29"))
                        defaultFps = 29.97;
                }
                isFirstLine = false;
            }
            sr.Close();
            return lines;
        }

        private static void CheckAssociation()
        {
            String path = "\"" + Assembly.GetExecutingAssembly().Location + "\" \"%1\"";

            RegistryKey regBase = Registry.CurrentUser.OpenSubKey("Software\\Classes");
            RegistryKey reg = regBase.OpenSubKey(".txt");
            if (reg == null)
            {
                regBase = Registry.ClassesRoot;
                reg = regBase.OpenSubKey(".txt");
            }
            String defaultForTxt = reg.GetValue("").ToString();

            reg = regBase.OpenSubKey(defaultForTxt, true);

            RegistryKey defReg = reg.OpenSubKey("shell", true);
            reg = defReg.OpenSubKey(REGISTRY_KEY, true);
            if (reg == null)
            {
                reg = defReg.CreateSubKey(REGISTRY_KEY);
                reg.SetValue("", Resources.ContextMenuItem);
                reg = reg.CreateSubKey("Command");
                reg.SetValue("", path);
            }
            else
            {
                RegistryKey regCommand = reg.OpenSubKey("Command", true);
                if (regCommand == null)
                {
                    reg = reg.CreateSubKey("Command");
                    reg.SetValue("", path);
                }
                else
                {
                    String v = regCommand.GetValue("").ToString();
                    if (!path.Equals(v))
                    {
                        regCommand.SetValue("", path);
                    }
                }
            }
        }
    }
}
